using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

namespace Super
{
	//游戏杂项管理
	public class InputManager : BaseSingle<InputManager>
	{
		/// <summary>
		/// 输入控制器
		/// </summary>
		private InputControl inputControl;
		public InputControl InputControl
		{
			get
			{
				if (inputControl == null)
				{
					inputControl = new InputControl();
					inputControl.Enable();
				}
				return inputControl;
			}
		}

		private CombBtnRunInfo rightRunInfo = new CombBtnRunInfo();
		private CombBtnRunInfo leftRunInfo = new CombBtnRunInfo();
		public FunBtnTwoInfo btnTwoInfo = new FunBtnTwoInfo();
		public MouseInfo mouseInfo = new MouseInfo();
		public bool isFirstUpdate = false;
		public bool isMouseOverUI = false;

		public override void OnInit()
		{
			base.OnInit();
			AddInputListen();

			SceneManager.sceneLoaded += OnSceneLoad;
			EventManager.Register<OnPlayerRunStateChange>(OnPlayerRunStateChange);
		}

		void Update()
		{
			UpdateMouseInfo();
			CheckIfMouseDrag();
			CheckIfInputDirection();

			CheckIfRunPost(leftRunInfo, inputControl.CombRun.LeftRun2);
			CheckIfRunPost(rightRunInfo, inputControl.CombRun.RightRun2);

			CheckIfHoldBtnTwo();
			
			isMouseOverUI = EventSystem.current.IsPointerOverGameObject();
			
			if (!isFirstUpdate)
			{
				isFirstUpdate = true;
				EventManager.Emit(new FirstUpdate());
			}
			EventManager.Emit(new UpdateGE(Time.deltaTime));
		}

		private void FixedUpdate()
		{
			EventManager.Emit(new OnFixedUpdateGE());
		}

		void OnApplicationFocus(bool focus)
		{
			if (!focus)
			{
				mouseInfo.hasMoved = false;
			}
		}

		/// <summary>
		/// 添加输入事件监听
		/// </summary>
		public void AddInputListen()
		{
			//鼠标
			foreach (var action in InputControl.Mouse.Get().actions)
			{
				action.performed += OnMouseBtnDown;
				action.canceled += OnMouseBtnUp;
			}

			//滚轮
			InputControl.MouseScroll.Scroll.performed += OnMouseScroll;

			//组合按钮
			InputControl.CombRun.LeftRun1.performed += (arg) => OnCombBtnRunPre(leftRunInfo);
			InputControl.CombRun.RightRun1.performed += (arg) => OnCombBtnRunPre(rightRunInfo);

			InputControl.CombAtk.DownAtk.performed += OnCombDownAtk;

			//功能按钮
			InputControl.FunBtnOne.Down.performed += OnFunBtnOneDown;

			InputControl.FunBtnTwo.Down.started += OnFunBtnTwoStart;
			InputControl.FunBtnTwo.Down.canceled += OnFunBtnTwoCancel;

			InputControl.FunBtnThree.Down.performed += OnFunBtnThreeDown;

			InputControl.FunBtnFour.Down.performed += OnFunBtnFourDown;

			InputControl.FunBtnFive.Down.performed += OnFunBtnFiveDown;

			InputControl.FunBtnSix.Down.performed += OnFunBtnSixDown;

			//其他按键
			InputControl.Esc.Down.performed += OnEscBtnDown;
			inputControl.Space.Down.performed += OnSpaceBtnDown;
			InputControl.Tab.Down.performed += OnTabBtnDown;
			InputControl.Q.Down.performed += OnQBtnDown;
			InputControl.E.Down.performed += OnEBtnDown;
			InputControl.W.Down.performed += OnWBtnDown;
			InputControl.A.Down.performed += OnABtnDown;
			InputControl.S.Down.performed += OnSBtnDown;
			InputControl.D.Down.performed += OnDBtnDown;

			InputControl.Num.One.performed += OnNumOneDown;
			InputControl.Num.Two.performed += OnNumTwoDown;
			InputControl.Num.Three.performed += OnNumThreeDown;
			InputControl.Num.Four.performed += OnNumFourDown;

		}

		
		#region 自定义事件

		public void SetCombBtnRunPre(bool isRight)
		{
			CombBtnRunInfo info = isRight ? rightRunInfo : leftRunInfo;
			OnCombBtnRunPre(info);
		}

		#endregion

		#region *********************Mouse*************************************
		public void OnMouseBtnDown(InputAction.CallbackContext context)
		{
			MouseKey key = (MouseKey)System.Enum.Parse(typeof(MouseKey), context.action.name);
			mouseInfo.holdKey = key;
			MouseDownGE eventData = new MouseDownGE(key);
			EventManager.Emit(eventData);
		}
		public void OnMouseBtnUp(InputAction.CallbackContext context)
		{
			MouseKey key = (MouseKey)System.Enum.Parse(typeof(MouseKey), context.action.name);
			MouseUpGE eventData = new MouseUpGE(key);
			EventManager.Emit(eventData);
		}

		/// <summary>
		/// 检测鼠标是否拖拽
		/// </summary>
		public void CheckIfMouseDrag()
		{
			bool isDrag = false;
			foreach (var action in InputControl.Mouse.Get().actions)
			{
				if (action.ReadValue<float>() >= ValueSettingSO.Ins.btnPressedThreshold)
				{
					MouseKey key = (MouseKey)System.Enum.Parse(typeof(MouseKey), action.name);
					mouseInfo.isHold = true;
					mouseInfo.holdKey = key;
					isDrag = true;
					EventManager.Emit(new MouseDragGE(key));
				}
			}
			
			if (!isDrag)
				mouseInfo.isHold = false;
		}

		public void UpdateMouseInfo()
		{
			mouseInfo.curPos = Mouse.current.position.ReadValue();
			if (mouseInfo.curPos != mouseInfo.prePos && !mouseInfo.hasMoved)
			{

				mouseInfo.hasMoved = true;
				mouseInfo.prePos = mouseInfo.curPos;
				return;
			}
			mouseInfo.offsetPos = mouseInfo.curPos - mouseInfo.prePos;
			mouseInfo.prePos = mouseInfo.curPos;
		}

		private void OnMouseScroll(InputAction.CallbackContext context)
		{
			EventManager.Emit(new MouseScrollGE(context.ReadValue<Vector2>()));
		}

		#endregion

		#region ********************************InputDirection**********************

		/// <summary>
		/// 事件通知方向输入的值
		/// </summary>
		private void CheckIfInputDirection()
		{
			Vector2 value = InputControl.Direction.Input.ReadValue<Vector2>();
			EventManager.Emit(new InputDirectionGE(value));

			float hValue = InputControl.Horizontal.Input.ReadValue<float>();
			EventManager.Emit(new InputHorizontalGE(hValue));

			float vValue = InputControl.Vertical.Input.ReadValue<float>();
			EventManager.Emit(new InputVerticalGE(vValue));
		}
		#endregion

		#region ********************************BtnOne**********************************
		public void OnFunBtnOneDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new FunBtnOneDownGE());
		}
		#endregion

		#region ********************************BtnTwo**********************************
		private void OnFunBtnTwoStart(InputAction.CallbackContext context)
		{
			btnTwoInfo.isPressed = true;
			btnTwoInfo.holdTime = 0;
			EventManager.Emit(new FunBtnTwoDownGE(true));
		}

		public void OnFunBtnTwoCancel(InputAction.CallbackContext context)
		{
			if (!btnTwoInfo.isPressed) return;

			btnTwoInfo.isPressed = false;
			EventManager.Emit(new FunBtnTwoDownGE(false));
		}
		private void CheckIfHoldBtnTwo()
		{
			if (!btnTwoInfo.isPressed) return;

			btnTwoInfo.holdTime += Time.deltaTime;
			if (btnTwoInfo.holdTime >= ValueSettingSO.Ins.btnJumpHoldTimeMax)
			{
				btnTwoInfo.isPressed = false;
				EventManager.Emit(new FunBtnTwoDownGE(false));
			}
		}
		#endregion

		#region ********************************BtnThree********************************
		public void OnFunBtnThreeDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new FunBtnThreeDownGE());
		}
		#endregion

		#region ********************************BtnFour**********************************
		public void OnFunBtnFourDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new FunBtnFourDownGE());
		}
		#endregion

		#region ********************************BtnFive**********************************
		public void OnFunBtnFiveDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new FunBtnFiveDownGE());
		}
		#endregion

		#region ********************************BtnSix**********************************
		public void OnFunBtnSixDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new FunBtnSixDownGE());
		}
		#endregion

		#region ********************************CombBtnRun**********************************
		public void OnCombBtnRunPre(CombBtnRunInfo info)
		{
			info.isRun1 = true;
			info.timerNode = new TimerNode(ValueSettingSO.Ins.btnTapThreshold, (TimerNode) => info.isRun1 = false);
			TimerManager.Register(this, info.timerNode);
		}

		/// <summary>
		/// 跑步状态不处理，取消跑步时重置状态
		/// </summary>
		/// <param name="evt"></param>
		public void OnPlayerRunStateChange(OnPlayerRunStateChange evt)
		{
			if (evt.state) return;

			leftRunInfo.isRun1 = false;
			leftRunInfo.isRun2 = false;
			TimerManager.UnRegister(leftRunInfo.timerNode);

			rightRunInfo.isRun1 = false;
			rightRunInfo.isRun2 = false;
			TimerManager.UnRegister(rightRunInfo.timerNode);
		}

		/// <summary>
		/// 检测是否奔跑
		/// </summary>
		/// <param name="info"></param>
		/// <param name="action"></param>
		public void CheckIfRunPost(CombBtnRunInfo info, InputAction action)
		{
			if (!info.isRun1) return;

			bool pressed = action.IsPressed();
			if (pressed)
			{
				EventManager.Emit(new CombBtnRunGE(true));
				TimerManager.UnRegister(info.timerNode);
				info.isRun1 = true;
				info.isRun2 = true;
			}

			if (info.isRun2 && !pressed)
			{
				EventManager.Emit(new CombBtnRunGE(false));
				info.isRun1 = false;
				info.isRun2 = false;
			}
		}
		#endregion

		#region ********************************CombAtk**********************************
		public void OnCombDownAtk(InputAction.CallbackContext context)
		{
			EventManager.Emit(new CombBtnDownAtkGE());
		}
		#endregion

		#region ********************************W**********************************
		private void OnWBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new WBtnDownGE());
		}
		#endregion

		#region ********************************A**********************************
		private void OnABtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new ABtnDownGE());
		}
		#endregion

		#region ********************************S**********************************
		private void OnSBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new SBtnDownGE());
		}
		#endregion

		#region ********************************D**********************************
		private void OnDBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new DBtnDownGE());
		}
		#endregion


		#region ********************************EscBtn**********************************
		private void OnEscBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new EscBtnDown());
		}
		#endregion
		
		#region ********************************Space**********************************
		private void OnSpaceBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new SpaceBtnDown());
		}
		#endregion
		
		#region ********************************TabBtn**********************************
		
		private void OnTabBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new TabBtnDown());
		}
		
		#endregion
		
		#region ********************************Q**********************************
		private void OnQBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new QBtnDownGE());
		}
		#endregion

		#region ********************************E**********************************
		private void OnEBtnDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new EBtnDownGE());
		}
		#endregion

		#region ********************************Num**********************************

		private void OnNumOneDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new NumBtnDown(1));
		}

		private void OnNumTwoDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new NumBtnDown(2));
		}

		private void OnNumThreeDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new NumBtnDown(3));
		}

		private void OnNumFourDown(InputAction.CallbackContext context)
		{
			EventManager.Emit(new NumBtnDown(4));
		}
		#endregion
		
		#region 回调
		
		private void OnSceneLoad(Scene scene, LoadSceneMode mode)
		{
			isFirstUpdate = false;
		}
		
		private void OnApplicationQuit()
		{
			EventManager.Emit(new ApplicationQuit());	
		}
		
		#endregion
	}

}
